package com.ruoyi.system.task;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.ruoyi.system.domain.PaperCheckPass;
import com.ruoyi.system.domain.PaperCheckResponse;
import com.ruoyi.system.enums.PaperStatusEnums;
import com.ruoyi.system.enums.YesOrNoEnum;
import com.ruoyi.system.service.IPaperCheckPassService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
public class SingleThreadScheduledTask {


    @Autowired
    private IPaperCheckPassService paperCheckPassService;

    @Autowired
    private Environment env;

    boolean isFirst = false;

    private static final OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .connectTimeout(10, java.util.concurrent.TimeUnit.SECONDS)  // 连接超时
            .readTimeout(30, java.util.concurrent.TimeUnit.SECONDS)     // 读取超时
            .build();

    /**
     * 定时更新db中所有待更新的论文
     * 0 0/3 * * * ?
     */
    @Scheduled(cron = "0/5 * * * * ?")
//    @Scheduled(cron = "0 0/5 * * * ?")
    public void updatePaperStatus() throws IOException {
        String isCheck = env.getProperty("checkPaper.isCheck");
        if (!isFirst) {
            log.info("updatePaperStatus,tempDir:{}", isCheck);
            isFirst = !isFirst;
        }

        if (!Boolean.parseBoolean(isCheck)) {
            return;
        }

        try {
            List<PaperCheckPass> paperList = paperCheckPassService.selectWaitCheckList();

            /**
             * 按照pddOrderId进行分组
             */
            Map<String, List<PaperCheckPass>> paperMap = paperList.stream().collect(Collectors.groupingBy(PaperCheckPass::getPddOrderId));
            for (Map.Entry<String, List<PaperCheckPass>> stringListEntry : paperMap.entrySet()) {
                String pddOrderId = stringListEntry.getKey();

                // https://api.checkpass.net/an/checkrecord?r=0.570156743683362&_user_token=oh6bS11bYGhfw5GZOW68fbQrAAw=&parameters[tid]=Y2506511480329182
                // 拼接完整的请求 URL，包含所有查询参数
                String url = "https://api.checkpass.net/an/checkrecord?" +
                        "_user_token=oh6bS11bYGhfw5GZOW68fbQrAAw=&" +
                        "parameters[tid]=" + pddOrderId + "&" +
                        "r=0.570156743683362";

                Request request = new Request.Builder()
                        .url(url)
                        .get()
                        .build();
                Response response = okHttpClient.newCall(request).execute();
                Assert.notNull(response, "updatePaperStatus response must not be null");
                Assert.isTrue(response.isSuccessful(),
                        "updatePaperStatuse must  be success!code:" + response.code());
                Assert.notNull(response.body(), "updatePaperStatus,response.body must not be null");
                String body = response.body().string();
                Assert.notBlank(body, "updatePaperStatus,response.body must not be blank");
                log.info("updatePaperStatus,response.code:{},response.body:{}", response.code(), body);

                PaperCheckResponse paperCheckResponse = JSON.parseObject(body, PaperCheckResponse.class);
                Assert.notNull(paperCheckResponse, "paperCheckResponse must not be null");
                Assert.notNull(paperCheckResponse.getDataWrapper(), "getDataWrapper must not be null");
                Assert.notEmpty(paperCheckResponse.getDataWrapper().getDataList(), "getDataList must not be null");

                /**2536338993646208814656
                 * 需要把paperDataList的数据和dbList做关联,关联的规则如下
                 * 1. paperDataList中的paperId和dbList中的paperId相等
                 */
                List<PaperCheckResponse.PaperData> paperDataList = paperCheckResponse.getDataWrapper().getDataList();
                List<PaperCheckPass> dbList = stringListEntry.getValue();

                Map<String, PaperCheckResponse.PaperData> apiPaperMap = paperDataList.stream().collect(Collectors.toMap(
                        PaperCheckResponse.PaperData::getPaperId,  // 键为 paperId
                        paper -> paper,  // 值为当前 PaperData 实体
                        (existing, replacement) -> {  // 冲突解决函数：比较 uploadTime，取较新的实体
                            // 定义时间格式（根据实际接口返回的格式调整）
                            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

                            // 解析现有实体的 uploadTime
                            LocalDateTime existingTime = LocalDateTime.parse(existing.getUploadTime(), formatter);
                            // 解析新实体的 uploadTime
                            LocalDateTime replacementTime = LocalDateTime.parse(replacement.getUploadTime(), formatter);

                            // 比较时间：如果新时间更晚，替换为新实体；否则保留现有实体
                            return replacementTime.isAfter(existingTime) ? replacement : existing;
                        }
                ));


                // 2. 遍历接口返回数据，通过Map快速匹配数据库记录
                for (PaperCheckPass dbPaper : dbList) {
                    try {
                        String paperId = dbPaper.getPaperId();

                        // 从Map中获取匹配的数据库记录（O(1)时间复杂度）
                        PaperCheckResponse.PaperData apiPaper = apiPaperMap.get(paperId);
                        Assert.notNull(apiPaper, "apiPaper must not be null");

                        // 3. 更新字段（与原代码一致）
                        String copyPercent = apiPaper.getCopyPercent();
                        String originPath = apiPaper.getOriginPath();
                        Integer status = apiPaper.getStatus();
                        String reportPath = apiPaper.getReportPath();
                        Assert.notNull(status, "status must not be null");

                        PaperCheckPass updatePaper = new PaperCheckPass();
                        updatePaper.setId(dbPaper.getId());
                        updatePaper.setCheckPaperStatusResult(JSON.toJSONString(apiPaper));
                        PaperStatusEnums checkPassCode = PaperStatusEnums.getByCheckPassCode(status);
                        Assert.notNull(checkPassCode, "checkPassCode status error:" + status);
                        if (checkPassCode.getCode().equals(PaperStatusEnums.FINISH.getCode())) {
                            updatePaper.setPaperStatus(PaperStatusEnums.FINISH.getCode());
                            updatePaper.setCopyPercent(copyPercent);
                            updatePaper.setOriginPath(originPath);
                            updatePaper.setReportPath(reportPath);
                        } else if (checkPassCode.getCode().equals(PaperStatusEnums.CHECKING.getCode())) {
                            updatePaper.setPaperStatus(PaperStatusEnums.CHECKING.getCode());
                        } else {
                            updatePaper.setPaperStatus(PaperStatusEnums.OTHER_ERROR.getCode());
                        }

                        Assert.isTrue(paperCheckPassService.updatePaperCheckPass(updatePaper),
                                "update paper fail!");
                    } catch (Exception e) {
                        log.error("update paper error!", e);
                    }
                }
            }
        } catch (Exception e) {
            log.error("update paper outer error!", e);
        }
    }


}
